#!/usr/bin/python
#
# DESCRIPTION
#
#   This script implements the add command for the external Linux/UNIX
#   application.
#
#   The add command is an input command.  The IDM engine sends an add command 
#   to the subscriber shim to request that the external application add an 
#   entry.
#
#
# VARIABLES
#
#   SRC_DN
#     Specifies the distinguished name of the entry to add, in the name space
#     of eDirectory.  When the IDM engine sends the add command, the subscriber
#     should copy the SRC_DN attribute to the outgoing DEST_DN command.
#
#   SRC_ENTRY_ID
#     Specifies the entry ID of the entry that generated the add event.  It is
#     specified in the name space of eDirectory.  When the IDM engine sends 
#     the add command, the subscriber should copy the SRC_ENTRY_ID attribute
#     to the outgoing DEST_ENTRY_ID command.
#
#   CLASS_NAME
#     Specifies the base class of the entry being added.
#
#   TEMPLATE_DN
#     Specifies the distinguished name, in the subscriber's name space, of the
#     template to use when creating the entry.
#
#   EVENT_ID
#     Specifies an identifier used to identify a particular instance of the 
#     command.
#
#   ADD_<ATTR_NAME>
#     Specifies an attribute name/value to add with the entry, where 
#     <ATTR_NAME> is literally replaced by the name of the attribute being
#     added.
#
#   PASSWORD
#     Specifies the initial password for the entry.
#
#
# REPLY FORMAT
#
#    The receiving application should respond to the add with a STATUS_LEVEL
#    and if the add suceeded, the subscriber must also return an ASSOCIATION.
#    Optionally, a STATUS_MESSAGE may also be returned to pass string messages
#    to the IDM engine for processing and logging.
#
#    If the add event does not contain values for all attributes defined in 
#    the create rules, the IDM engine discards the add command for the entry.
#    When a modify command is received for this entry, IDM queries eDirectory
#    for the missing attributes.  If all attributes now have values, IDM 
#    changes the modify into an add command.
#
#    The format for returning ASSOCIATION, DEST_DN, DEST_ENTRY_ID, EVENT_ID, 
#    STATUS, STATUS_MESSAGE are as follows:
#
#      idmsetvar("ASSOCIATION", <association>)
#      idmsetvar("DEST_DN", <dest_dn>)
#      idmsetvar("DEST_ENTRY_ID", <dest_entry_id>)
#      idmsetvar("EVENT_ID", <event_id>)
#
#      status_<level>("<optional message>")
#
#        <level> may be one of the following values:
#        * success
#        * warning
#        * error
#        * retry
#        * fatal
#
#      Note:  fatal will shutdown the driver, retry will retry the event
#             later on.
#

# include the IDM Library
from idmlib import *
from globals import *

import MySQLdb
import sys

g = GlobalSettings()

logger("debug", "add.py", " add called ")
trace(" add.py ")

# retrieve any necessary information from the shim, such as CLASS_NAME 
# of the object being added
class_name = idmgetvar("CLASS_NAME")

# retrieve the provisioning user and password from the driver
mysqlprovuser = idmgetdrvvar("mysqlprovuser");
mysqlprovpw = idmsubgetnamedpassword("mysqlprovpw");

# INSERT CUSTOM CODE HERE

SRC_DN = idmgetvar("SRC_DN")
SRC_ENTRY_ID = idmgetvar("SRC_ENTRY_ID")
EVENT_ID = idmgetvar("EVENT_ID")

dbname = idmgetvar("ADD_CN") 
dbhost = idmgetvar("ADD_HOST") 

publish_dbhost = ''
publish_dbport = ''

if (dbhost == ''):
    dbhost = g.defaults['dbhost']
    publish_dbhost = dbhost

dbport = idmgetvar("ADD_PORT")
if (dbport == ''):
    dbport = g.defaults['dbport']
    publish_dbport = dbport

dbgrantsets = idmgetvar("ADD_GRANTSETS").splitlines(0)

# Check var input for validity
if (dbname == ''):
    status_error("Missing database name to create!")
    sys.exit(0)
if (dbhost == ''):
    status_error("Missing database host!")
    sys.exit(0)
if (dbport == ''):
    status_error("Missing database port!")
    sys.exit(0)
if (mysqlprovuser == ''):
    status_error("Missing mysql provisioning user!")
    sys.exit(0)
if (mysqlprovpw == ''):
    status_error("Missing mysql provisioning password!")
    sys.exit(0)

# Get a Database Connection
try:
    conn = MySQLdb.connect (host = dbhost,
                             user = mysqlprovuser,
                             passwd = mysqlprovpw,
                             port = dbport)
except MySQLdb.Error, e:
    status_error("MYSQL ERROR %d: %s" % (e.args[0], e.args[1]))
    sys.exit (0)
except KeyError:
    status_error("Key Error:  Most likely cause is using an invalid dbhost, or \
    missing privileged user/pass for dbhost")
    sys.exit (0)
except:
    status_error("An unexpected error occured while trying to connect mysql on: " + dbhost)
    sys.exit(0)




# Make sure the database doesn't already exist, then if not, create it.
try:
     cursor = conn.cursor ()
     cursor.execute ("SHOW DATABASES LIKE '" + MySQLdb.escape_string(dbname) + "'");
     if (cursor.rowcount > 0):
        cursor.close () 
        status_error("Attempting to create database: (" + dbname + ").  Already exists!")
        sys.exit(0)
     cursor.execute ("CREATE DATABASE `" + MySQLdb.escape_string(dbname) + "`");
     if (cursor.rowcount > 0):
         pass # success
     else:
         #failure
         e = MySQLdb.Error(99991,"Failure creating database: (" + dbname + ").")
         raise e
         
except MySQLdb.Error, e:
    status_error("MYSQL ERROR %d: %s" % (e.args[0], e.args[1]))
    sys.exit (0) 
    
    
    
    
# Grant Privs on the database according to the info in the GRANTSETS attribute     
try:           
     for value in dbgrantsets:
        (userid,passwd,hostpattern) = value.split('||')
             
        # Build up the grant string
        grantstr = 'GRANT ALL PRIVILEGES ON ' + MySQLdb.escape_string(dbname) + '.* ' + 'TO '\
                    + MySQLdb.escape_string(userid) + " @'"\
                    + MySQLdb.escape_string(hostpattern) + "' IDENTIFIED BY '"\
                    + MySQLdb.escape_string(passwd) + "';"
             
        # make it happen       
        cursor.execute (grantstr)
              
     #If we got this far, the create and Grants are done.  Lets cleanup the database connection 
     cursor.execute ("FLUSH PRIVILEGES;")        
     conn.commit ()
     cursor.close ()

except MySQLdb.Error, e:
    status_error("MYSQL ERROR %d: %s: Attempting to drop just created database %s" %\
                (e.args[0], e.args[1], dbname))
    cursor.execute ("DROP DATABASE " + MySQLdb.escape_string(dbname) )
    cursor.close ()
    sys.exit (0)
    

# Retrieve additional information about the event and send back an
# association for this object along with a status document


our_association = dbname + '@' + dbhost + '@' + str(dbport)

idmsetvar("COMMAND","ADD_ASSOCIATION")
idmsetvar("ASSOCIATION",dbname + '@' + dbhost + '@' + str(dbport))
idmsetvar("DEST_DN",SRC_DN)
idmsetvar("DEST_ENTRY_ID",SRC_ENTRY_ID)
idmsetvar("EVENT_ID",EVENT_ID)
status_success("OK")

##Ok, before we leave, lets set host and port back on the object if they came back empty
##And also set the dbadmin url.
# submit event to the publisher changelog 

local_usclh = os.environ.get('INSTALL_PATH') + "bin/usclh"

usclh = os.popen(local_usclh + " -t modify -c mysqlDatabase -a " + our_association, 'w') 
usclh.write("ADD_ADMINURL"  + "=" + g.provisionable_servers[publish_dbhost]['purl']) 

if (publish_dbhost != ''):
   #we need to publish the host  
   usclh.write("\nADD_HOST"  + "=" + publish_dbhost) 
   pass
if (publish_dbport != ''):
   #we need to publish the port
   usclh.write("\nADD_PORT" + "=" + str(publish_dbport)) 
   pass

#logger("debug", "add.py", " phpmyadmin is at: " + g.provisionable_servers[publish_dbhost]['purl'])
#close the connection
usclh.close()

